//
//  YNSessionMessageManager.m
//  Messenger
//
//  Created by yineng on 2019/8/20.
//  Copyright © 2019 YN-APP-iOS. All rights reserved.
//

#import "YNSessionMessageManager.h"
#import "XMPPFramework.h"
#import "YNMessage.h"
#import "YNIMTool.h"
#import "YNIMFrameworkMacro.h"
#import "YNSessionOpenfireManager.h"

#if DEBUG
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // | XMPP_LOG_FLAG_TRACE;
#else
static const int xmppLogLevel = XMPP_LOG_LEVEL_OFF;
#endif

#define ReceiptTimeOut 60
#define YNXMPP_IQ_TIMEOUT 10

@interface YNSessionMessageManager ()
{
    XMPPIDTracker *xmppIDTracker;
}
@end

@implementation YNSessionMessageManager

- (instancetype)init
{
    self =  [super initWithDispatchQueue:NULL];
    if (self) {
        debugLog(@"云端openfire消息接收发送类初始化了");
    }
    return self;
}

- (BOOL)activate:(XMPPStream *)aXmppStream
{
    XMPPLogTrace();
    if ([super activate:aXmppStream])
    {
        XMPPLogVerbose(@"%@: Activated", THIS_FILE);
        xmppIDTracker = [[XMPPIDTracker alloc] initWithStream:xmppStream dispatchQueue:moduleQueue];
        return YES;
    }
    return NO;
}

- (void)deactivate
{
    XMPPLogTrace();
    dispatch_block_t block = ^{ @autoreleasepool {
        [xmppIDTracker removeAllIDs];
        xmppIDTracker = nil;
    }};
    if (dispatch_get_specific(moduleQueueTag)) {
        block();
    }else {
        dispatch_sync(moduleQueue, block);
    }
    [super deactivate];
}

-(void)sendIQUnlockRoom{
    dispatch_block_t block = ^{ @autoreleasepool{
        XMPPIQ *iq = [XMPPIQ iqWithType:@"set" elementID:[XMPPStream generateUUID]];
        [iq addAttributeWithName:@"from" stringValue:xmppStream.myJID.description];
        [iq addAttributeWithName:@"to" stringValue:[NSString stringWithFormat:@"%@@conference.%@/%@",self.roomId ,openfireDomainName,[YNIMmanager sharedInstance].userImId]];
        
        NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:XMPPMUCOwnerNamespace];
        NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"jabber:x:data"];
        [x addAttributeWithName:@"type" stringValue:@"submit"];
        [query addChild:x];
        [iq addChild:query];
        
        debugLog(@"云端openfire发送解锁房间的iq消息：%@",iq);
        [xmppIDTracker addID:[iq elementID]
                      target:self
                    selector:@selector(sendIQUnlockRoomChat:withInfo:)
                     timeout:YNXMPP_IQ_TIMEOUT];
        
        [xmppStream sendElement:iq];
        
    }};
    
    if (dispatch_get_specific(moduleQueueTag)) {
        
        block();
        
    }else {
        
        dispatch_async(moduleQueue, block);
    }
}
- (void)sendIQUnlockRoomChat:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)basicTrackingInfo{
    debugLog(@"发送解锁房间iq消息的回调消息===%@",iq);
}

-(void)sendPresenceJoinTRTCRoom:(NSString*)roomId{
    XMPPPresence *presence = [XMPPPresence presenceWithType:nil to:[XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@%@/%@",roomId, @"conference.",openfireDomainName,[YNIMmanager sharedInstance].userImId]]];
    NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:XMPPMUCNamespace];
    [presence addChild:x];
    debugLog(@"云端openfire发送加入房间的presence消息：%@",presence);
    [xmppStream sendElement:presence];
}

-(void)sendMessageChangeSubjectSpeakIds:(NSArray<NSDictionary*>*)speaks{
    if ([YNIMTool isEmptyString:self.roomId]) {
        return;
    }
    if ([YNIMTool isEmptyArray:speaks]) {
        speaks=@[];
    }
    dispatch_block_t block = ^{ @autoreleasepool {
        XMPPMessage *msg = [XMPPMessage messageWithType:@"groupchat" to:[XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.%@",self.roomId,openfireDomainName]]];
        
        [msg addAttributeWithName:@"from" stringValue:xmppStream.myJID.description];
        [msg addAttributeWithName:@"id" stringValue:[XMPPStream generateUUID]];
        ////加入这个数据，为了兼容消息发到老版本应用里解析不出的问题
        NSMutableArray*speakIds=[NSMutableArray array];
        for (NSDictionary*speakDic in speaks) {
            if (![YNIMTool isEmptyString:speakDic[@"userId"]]) {
                [speakIds addObject:speakDic[@"userId"]];
            }
        }
        
        NSString*subjectJson=[YNIMTool jsonStringWithObject:@{@"speaks":speaks,@"speakIds":speakIds}];
        NSXMLElement *subject = [NSXMLElement elementWithName:@"subject" stringValue:subjectJson];
        [msg addChild:subject];
        
        debugLog(@"云端openfire发送变更主题的message：%@",msg);
        [xmppIDTracker addID:[msg elementID] block:^(XMPPIQ *iq, id <XMPPTrackingInfo> info){
            if (iq) {
                //发送成功
            }else{
                //发送失败
            }
        }timeout:ReceiptTimeOut];
        [xmppStream sendElement:msg];
    }};
    
    if (dispatch_get_specific(moduleQueueTag)) {
        block();
    }else {
        dispatch_async(moduleQueue, block);
    }
}

-(void)sendMessageWith:(NSString*)body toUserId:(NSString*)toUserId message:(YNMessage*)message netConnect:(BOOL)netConnect{
    if ([YNIMTool isEmptyString:self.roomId]) {
        return;
    }
    if ([YNIMTool isEmptyString:body]) {
        body=@"";
    }
    if ([YNIMTool isEmptyString:toUserId]) {
        toUserId=@"";
    }
    
    dispatch_block_t block = ^{ @autoreleasepool {
        NSString*toString=[NSString stringWithFormat:@"%@@conference.%@/%@",self.roomId,openfireDomainName,toUserId];
        NSString*typeStr=@"chat";
        if ([YNIMTool isEmptyString:toUserId]) {
            toString=[NSString stringWithFormat:@"%@@conference.%@",self.roomId,openfireDomainName];
            typeStr=@"groupchat";
        }
        XMPPMessage *msg = [XMPPMessage messageWithType:typeStr to:[XMPPJID jidWithString:toString]];
        
        [msg addAttributeWithName:@"from" stringValue:xmppStream.myJID.description];
        if (![YNIMTool isEmptyString:message.packetId]) {
            [msg addAttributeWithName:@"id" stringValue:message.packetId];
        }else{
            [msg addAttributeWithName:@"id" stringValue:[XMPPStream generateUUID]];
        }
        
        NSXMLElement *subject = [NSXMLElement elementWithName:@"body" stringValue:body];
        [msg addChild:subject];
        
        debugLog(@"云端openfire发送message消息：%@",msg);
        [xmppIDTracker addID:[msg elementID] block:^(XMPPIQ *iq, id <XMPPTrackingInfo> info){
            if (iq) {
                //发送成功
            }else{
                //发送失败
            }
        }timeout:ReceiptTimeOut];
        [xmppStream sendElement:msg];
        
        //发送了过后只要网络是通的，就默认是成功的
        if (!netConnect) {
             message.sendState = YNMessageSendStateFailed;
        }else{
            message.sendState = YNMessageSendStateSuccess;
            message.sendTime = [YNIMTool dateStringFromCurrentDate];
            message.currentTime=[YNIMTool dateStringFromCurrentDate];
        }
        //通知更新会话界面
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationLiveMessageReceipt object:message];
        });
        
    }};
    
    if (dispatch_get_specific(moduleQueueTag)) {
        block();
    }else {
        dispatch_async(moduleQueue, block);
    }
}

#pragma mark XMPPStream Delegate
//接受消息
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{
    debugLog(@"云端openfire收到message消息：%@",message);
    //当收到type为error的消息要拦截
    if (![YNIMTool isEmptyString:[message type]]) {
        if ([[message type] isEqualToString:@"error"]) {
            return;
        }
    };
    YNMessage *msg = [[YNMessage alloc] initWithXMPPMessage:message messageSourceType:GroupMessageSourceType_online isFromSessionListLastMessage:NO];
    //移除下数据，保证数据正确的保险
    [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"enterVideoMeetingGetedSpeakIdsData"];
    [[NSUserDefaults standardUserDefaults]synchronize];
    if (![YNIMTool isEmptyString:msg.subject]) {
        NSDictionary*subDic=[YNIMTool getJsonObjectFromJsonString:msg.subject];
        NSArray<NSDictionary*>*speaks=(NSArray*)subDic[@"speaks"];
        
        if (![YNIMTool isEmptyArray:speaks]) {
            //要防止空的字段存入NSUserDefaults
            NSMutableArray*teamArra=[NSMutableArray array];
            for (NSDictionary*speakDic in speaks) {
                NSDictionary*teamDic=@{
                    speakObjectUserName:[YNIMTool isEmptyString:speakDic[speakObjectUserName]] ? @"" : speakDic[speakObjectUserName],
                                       speakObjectUserId:[YNIMTool isEmptyString:speakDic[speakObjectUserId]] ? @"" : speakDic[speakObjectUserId],
                                       speakObjectGender:[YNIMTool isEmptyString:speakDic[speakObjectGender]] ? @"" : speakDic[speakObjectGender],
                    speakObjectHeadUrl:[YNIMTool isEmptyString:speakDic[speakObjectHeadUrl]] ? @"" : speakDic[speakObjectHeadUrl],
                };
                [teamArra addObject:teamDic];
            }
            [[NSUserDefaults standardUserDefaults]setObject:teamArra forKey:@"enterVideoMeetingGetedSpeakIdsData"];
            [[NSUserDefaults standardUserDefaults]synchronize];
        }
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter]postNotificationName:YNNotificationCloudOpenfirReciveMessage object:msg];
    });
}

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq{
    debugLog(@"云端openfire收到iq消息：%@",iq);
    return YES;
}

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence{
    debugLog(@"云端openfire收到presence消息：%@",presence);
    
    NSXMLElement *errorElement = [presence elementForName:@"error"];
    if (errorElement) {
        NSString*type= [errorElement attributeStringValueForName:@"type"];
        NSString*code= [errorElement attributeStringValueForName:@"code"];
        if ([type isEqualToString:@"cancel"]&&[code isEqualToString:@"404"]) {
            //加入房间时房屋还没解锁，出现这种错误时，停顿一下在加入房间就可以了
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self sendPresenceJoinTRTCRoom:self.roomId];
            });
        }else{
            //不知是什么错
            if (self.joinRoomFailBlock) {
                self.joinRoomFailBlock(@"");
            }
        }
        return;
    }
    NSXMLElement *xElement = [presence elementForName:@"x"];
    if (xElement) {
        NSArray*statusArra=[xElement elementsForName:@"status"];
        if (![YNIMTool isEmptyArray:statusArra]) {
            BOOL meIsRoomCreater=NO;
            BOOL joinRoomSuccess=NO;
            for (NSXMLElement*statusElement in statusArra) {
                NSString*code= [statusElement attributeStringValueForName:@"code"];
                if ([code isEqualToString:@"110"]) {
                    joinRoomSuccess=YES;
                }
                if ([code isEqualToString:@"201"]) {
                    meIsRoomCreater=YES;
                }
            }
            if (meIsRoomCreater) {
                //我是房间创建人 发送变更主题的message 还要发送解锁房间的iq
                [self  sendMessageChangeSubjectSpeakIds:@[]];
                [self sendIQUnlockRoom];
                if (self.joinRoomSuccessBlock) {
                    self.joinRoomSuccessBlock();
                }
            }else if (joinRoomSuccess){
                //我不是房间创建人 但我加入成功
                if (self.joinRoomSuccessBlock) {
                    self.joinRoomSuccessBlock();
                }
            }
        }else{
            //可能是人员进出的消息
            NSXMLElement *item  = [xElement elementForName:@"item"];
            if (!item) return;
            NSString*jidStr =[item attributeStringValueForName:@"jid"];
            if (!jidStr) return;
            NSArray*jidArra=[jidStr componentsSeparatedByString:@"@"];
            if (jidArra.count<=1) return;
            NSString*userId=jidArra[0];
            NSString*affiliation=[presence attributeStringValueForName:@"type"];
            BOOL isUserComeIn=YES;
            if ([affiliation isEqualToString:@"unavailable"]) {
                //人员退出
                isUserComeIn=NO;
            }else{
                //人员进入
                isUserComeIn=YES;
                if (self.inRoomUserBlock) {
                    self.inRoomUserBlock(userId);
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                [[NSNotificationCenter defaultCenter]postNotificationName:YNNotificationCloudOpenfirMemberChange object:userId userInfo:@{@"status":@(isUserComeIn)}];
            });
        }
    }
}

@end
